#include "EbnModelFactory.h"
#include "EbnModelController.h"
#include "EbnModel.h"
#include "EbnWorldStateManager.h"
#include "EbnActionManager.h"

#include "EbnXmlStringREf.h"

CEbnModelFactory::CEbnModelFactory(CEbnModelController * controller)
{
    mpController = controller;
    mpModel = mpController->getModel();
    mpWorldStateManager = mpController->getWorldStateManager();
    mpActionManager = mpController->getActionManager();
}

CEbnModelFactory::~CEbnModelFactory()
{
    mpModel = NULL;
    mpWorldStateManager = NULL;
    mpActionManager = NULL;
}

bool CEbnModelFactory::loadFile(const QString & filename)
{
    QFile file(filename);
    QXmlInputSource inputSource(&file);
    QXmlSimpleReader reader;
    reader.setContentHandler(this);
    reader.setErrorHandler(this);

    return reader.parse(inputSource);
}

bool CEbnModelFactory::startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &atts)
{
    if (qName == EBN_WORLD_STATE)
    {
        mpWorldStateManager->addWorldState(atts.value(EBN_WORLD_STATE_NAME).toStdString());

        if (-1 != atts.index(EBN_WORLD_STATE_TRUTH_VALUE))
        {
            mpWorldStateManager->setWorldStateValue(atts.value(EBN_WORLD_STATE_NAME).toStdString(),
                                                    atts.value(EBN_WORLD_STATE_TRUTH_VALUE).toFloat());
        }
    }
    else if (qName == EBN_ACTION)
    {
        CEbnAction * action = mpActionManager->addAction(atts.value(EBN_ACTION_NAME).toStdString());
        if (-1 != atts.index(EBN_ACTION_ANIMATION))
        {
            action->setAnimation(atts.value(EBN_ACTION_ANIMATION).toStdString());
        }
    }
    else if (qName == EBN_GOAL)
    {
        CEbnWorldState * worldState = mpWorldStateManager->getWorldState(atts.value(EBN_GOAL_NAME).toStdString());
        CEbnGoal * goal = new CEbnGoal(worldState);

        mpCurrentGoal = goal;
    }
    else if (qName == EBN_RECEPTOR)
    {
        CEbnWorldState * worldState = mpWorldStateManager->getWorldState(atts.value(EBN_RECEPTOR_NAME).toStdString());
        CEbnReceptor * receptor = new CEbnReceptor(worldState);

        mpCurrentReceptor = receptor;
    }
    else if (qName == EBN_COMPETENCE_MODULE)
    {
        CEbnAction * action = mpActionManager->getAction(atts.value(EBN_COMPETENCE_MODULE_ACTION_NAME).toStdString());
        CEbnCompetenceModule * cm = new CEbnCompetenceModule(action);

        mpCurrentCompetenceModule = cm;
    }
    else if (qName == EBN_CONDITION)
    {
        if(mpCurrentCompetenceModule)
        {
            CEbnWorldState * worldState = mpWorldStateManager->getWorldState(atts.value(EBN_CONDITION_NAME).toStdString());
            mpCurrentCompetenceModule->addCondition(worldState);
        }
    }
    else if (qName == EBN_EFFECT)
    {
        if(mpCurrentCompetenceModule)
        {
            CEbnWorldState * worldState = mpWorldStateManager->getWorldState(atts.value(EBN_EFFECT_NAME).toStdString());
            mpCurrentCompetenceModule->addPostEffect(worldState);
        }
    }
    else if (qName == EBN_ACTION_TRIGGER)
    {
        mpController->addActionTrigger(atts.value(EBN_ACTION_TRIGGER_ACTION).toStdString(),
                                       atts.value(EBN_ACTION_TRIGGER_WORLD_STATE).toStdString(),
                                       atts.value(EBN_ACTION_TRIGGER_VALUE).toFloat());
    }
    else if (qName == EBN_MODEL)
    {
        if (-1 != atts.index(EXHIBITION_OF_MODULE))
        {
            mpModel->getNetParamManager()->setExhibitionOfModule(atts.value(EXHIBITION_OF_MODULE).toFloat());
        }

        if (-1 != atts.index(INHIBITION_OF_MODULE))
        {
            mpModel->getNetParamManager()->setInhibitionOfModule(atts.value(INHIBITION_OF_MODULE).toFloat());
        }

        if (-1 != atts.index(EXHIBITION_OF_STATE))
        {
            mpModel->getNetParamManager()->setExhibitionOfState(atts.value(EXHIBITION_OF_STATE).toFloat());
        }

        if (-1 != atts.index(INERTIA_OF_ACTIVATION))
        {
            mpModel->getNetParamManager()->setInertiaOfActivation(atts.value(INERTIA_OF_ACTIVATION).toFloat());
        }

        if (-1 != atts.index(EXECUTABILITY_THRESHOLD))
        {
            mpModel->getNetParamManager()->setExecutabilityThreshold(atts.value(EXECUTABILITY_THRESHOLD).toFloat());
        }

        if (-1 != atts.index(THERSHOLD_DECAY))
        {
            mpModel->getNetParamManager()->setThresholdDecay(atts.value(THERSHOLD_DECAY).toFloat());
        }

        if (-1 != atts.index(UPPER_BOUND_OF_ACTIVATION_THRESHOLD))
        {
            mpModel->getNetParamManager()->setUpperBoundOfActivationThreshold(atts.value(UPPER_BOUND_OF_ACTIVATION_THRESHOLD).toFloat());
        }
    }

    return true;

}

bool CEbnModelFactory::endElement(const QString &namespaceURI, const QString &localName, const QString &qName)
{
    if (qName == EBN_GOAL)
    {
        if (mpCurrentGoal)
        {
            mpModel->addGoal(mpCurrentGoal);
            mpCurrentGoal = NULL;
        }
    }
    else if (qName == EBN_RECEPTOR)
    {
        if (mpCurrentReceptor)
        {
            mpModel->addReceptor(mpCurrentReceptor);
            mpCurrentReceptor = NULL;
        }
    }
    else if (qName == EBN_COMPETENCE_MODULE)
    {
        if (mpCurrentCompetenceModule)
        {
            mpModel->addCompetenceModule(mpCurrentCompetenceModule);
            mpCurrentCompetenceModule = NULL;
        }
    }
    return true;
}

bool CEbnModelFactory::characters(const QString &ch)
{
    return true;
}

bool CEbnModelFactory::fatalError(const QXmlParseException &exception)
{
    return true;
}
